/*
 * operation_usage.cpp
 *
 *  Created on: 2009-8-27
 *      Author: ws
 */

#include<machine/m_bw.h>
#include<Lcode/l_main.h>

#include"Operation.hpp"
#include"operation_usage.hpp"



int Numof_Resource( enum _Function_Type ft)
{
	switch (ft)
	{
		case FT_ALU:
			return 8;
		case FT_MUL:
			return 4;
		case FT_Shifter:
			return 2;
		case FT_ASPU:
			return 2;
		case FT_BUS_X:
		case FT_BUS_Y:
		case FT_BUS_Z:
		case FT_BUS_T:
			return 3;
		default :
			L_punt("Numof_Resource: unexpected Function_Type");
	}
}

const char * get_resource_name(enum _Function_Type ft)
{
	switch (ft)
	{
		case FT_ALU :
			return "FT_ALU";
		case FT_MUL :
			return "FT_MUL";
		case FT_Shifter:
			return "FT_Shifter";
		case FT_ASPU:
			return "FT_ASPU";
		case FT_ALU_agu:
			return "FT_ALU_agu";
		case FT_BUS_X:
			return "FT_BUS_X";
		case FT_BUS_Y:
			return "FT_BUS_Y";
		case FT_BUS_Z:
			return "FT_BUS_Z";
		case FT_BUS_T:
			return "FT_BUS_T";
		default:
			L_punt("get_resource_name : unexpected Fuction_Type");
	}
}

/*
 * return the resource of the operation  using;
 *
 */

UsageFU Get_Operation_Usage( Instruction* n  )
{
	int proc_opc = n->get_proc_opc();
	UsageFU xx;
	switch(proc_opc)
	{
		case  LBWop_MOV_GR  		:   /*Rm=Rn    Move between general registers */
		case  LBWop_MOV_IMM32_S :  /*Rm=C */
		case  LBWop_MOV_IMM32_U :  /*Rm=C (u)*/
		case  LBWop_MOV_IMM32_F :  /*FRm=C */
			xx.push_usage(FT_IMM, NO_CORE, 0);
			return xx;
		case  LBWop_ADD_F :  /*FRs=Rm+Rn*/
		case  LBWop_ADD_U :  /*Rs=Rm+Rn(u) */
		case  LBWop_ADD_S : /*Rs=Rm+Rn*/
		case  LBWop_INC_IMM12_S:/*Rs=Rs+c*/
		case  LBWop_ADD_ADDR:/*Us=Un+Un*/
		case  LBWop_ADD_ADDR_IMM8:/*Us=Un+C  */
		case  LBWop_ADD_2X16:/*HRs=Rn+Rm*/
		case  LBWop_ADD_SUB:/*Rm_n=Rm+Rn*/
			xx.registe(FT_ALU, 0, n);
			return xx;

		case  LBWop_MUL_U:/*Rs=Rm*Rn(u)*/
		case  LBWop_MUL_S:/*Rs=Rm*Rn*/
		case  LBWop_MUL_F:/*FRs=Rm*Rn*/
			xx.registe(FT_MUL, 0,n);
			return xx;
		case   LBWop_MUL_ADD_F:/*FMacc+=Rm*Rn*/
		case   LBWop_MUL_ADD_U:/*Macc+=Rm*Rn(u)*/
		case   LBWop_MUL_ADD_S:/*Macc+=Rm*Rn*/
			xx.registe(FT_MUL, 0,n);
			xx.registe(FT_ALU, 0,n);
			return xx;

		case  LBWop_SUB_F:/*FRs=Rm-Rn*/
		case  LBWop_SUB_U:/*Rs=Rm-Rn(u)*/
		case  LBWop_SUB_S:/* Rs=Rm-Rn*/
			xx.registe(FT_ALU, 0,n);
			return xx ;

		case  LBWop_MUL_SUB_F:/*FMacc-=Rm*Rn*/
		case  LBWop_MUL_SUB_U:/*Macc-=Rm*Rn(u)*/
		case  LBWop_MUL_SUB_S:/*Macc-=Rm*Rn*/
			xx.registe(FT_MUL, 0,n);
			xx.registe(FT_ALU, 0,n);
			return xx;
		case  LBWop_SUB_COMPLEX:/*CRs+1:s=CRm+1:m-CRn+1:n*/
		case  LBWop_SUB_COMPLEX_F:/*CFRs+1:s=CRm+1:m-CRn+1:n*/
			xx.registe(FT_ALU, 0,n);
			xx.registe(FT_ALU, 0,n);
			return xx;
		case  LBWop_LD:
		case  LBWop_LD_IMM16_IMM7:
		case  LBWop_LD_IMM16:
		case  LBWop_LD_IMM7:

	/*[base , offset, word_offset]*/
		case  LBWop_ST:/*[reg, reg, reg] */
		case  LBWop_ST_IMM16_IMM7:/*[reg, imm16, imm7]*/
		case  LBWop_ST_IMM16:/*[reg, imm16, reg]*/
		case  LBWop_ST_IMM7:/* [reg, reg, imm7]*/
			xx.push_usage(FT_STORE,NO_CORE ,0 );

			return xx;

		case  LBWop_FEXT_IMM:
			xx.push_usage(FT_IMM, NO_CORE, 0);
			xx.registe(FT_ALU, 0,n);
			return xx;

		case  LBWop_SHIFT_ROT_IMM6:
		case  LBWop_ZXT:/* Rm=EXPAND(LHRM,a)(U)  a=0   */
		case  LBWop_SXT:/* Rm=EXPAND(LHRM,a)     a=0   */
		case  LBWop_SXT_C2:/*Rn=expand(LHRn a) a=0*/
			xx.registe(FT_ALU, 0,n);
			return xx;

		case  LBWop_LSHIFT:/*Rs=Rm lshift Rn*/
		case  LBWop_ASHIFT:/*Rs=Rm ashift Rn*/
		case  LBWop_LSHIFT_IMM6:/* Rn= Rs lshift a  a>0 shift left a<0 shift right */
		case  LBWop_ASHIFT_IMM6:/* */
			xx.registe(FT_Shifter, 0, n);
			return xx;

		case  LBWop_COMPACT64:/*CHRs=COMPACT(CRm+1:m,Rn)*/
		case  LBWop_EXPAND32:/*CRs+1:s=EXPAND(CHRm,Rn)*/
			xx.registe(FT_ALU, 0,n);
			return xx;

		case  LBWop_COMB_U:/* if {x,y,z,t}Rm >Rn B <pro>*/
		case  LBWop_COMB_S:
		case  LBWop_COMB_F:/*if*/
			xx.registe(FT_ALU, 0,n);
			return xx;

		case  LBWop_JUMP:/*B BA  */
		case  LBWop_JSR_SR:
		case  LBWop_JSR:/*call label and call SR */
		case  LBWop_RTS:/* RET */
			return xx;


		case   LBWop_ADD_2X16_HIGH:/*HHRm=HHRm+LHRm */
		case   LBWop_ADD_2X16_LOW:/*LHHRm=HHRm+LHRm*/
			xx.registe(FT_ALU, 0,n);
			return xx;

		case   LBWop_F_I:/*Rs=FIX FRs*/
		case   LBWop_I_F:/*FRs = FLOAT Rs*/
		case   LBWop_AND:/*Rs=Rm and Rn*/
		case   LBWop_OR:/*Rs=Rm or Rn*/
		case   LBWop_XOR:/*Rs=Rm ^ Rn */
			xx.registe(FT_ALU, 0,n);
			return xx;

		case   LBWop_MAX_S:
		case   LBWop_MAX_F:
		case   LBWop_MAX_U:
		case   LBWop_MIN_S:
		case   LBWop_MIN_F:
		case   LBWop_MIN_U:
			xx.registe(FT_ALU, 0,n);
			return xx;


		case   LBWop_ADD_S_HALF:/*Rs=(Rm+Rn)/2*/
		case   LBWop_SUB_S_HALF:
		case   LBWop_ADD_F_HALF:
		case   LBWop_SUB_F_HALF:
		case   LBWop_ADD_SUB_S:
		case   LBWop_ADD_SUB_F:
		case   LBWop_ADD_SUB_S_HALF:
		case   LBWop_ADD_SUB_F_HALF:
			xx.registe(FT_ALU_agu, 0,n);
			return xx;

		case   LBWop_CNT_ZERO_IMM5:
		case   LBWop_CNT_ONE_IMM5:
		case   LBWop_ACF_OUT:
		case   LBWop_MACC_OUT:
		case   LBWop_ASM:/*for the inline asm*/
		case   LBWop_NON_INSTR:
			xx.registe(FT_ALU, 0,n);
			return xx;

		/************************************/
		/*wansheng modify*/

		case   LBWop_ADD_ADDR_u:/*Us=Un+Un*/
		case   LBWop_ADD_ADDR_v:/*Us=Un+Un*/
		case   LBWop_ADD_ADDR_w:/*Us=Un+Un*/
		case   LBWop_ADD_ADDR_IMM8_u:/*Us=Un+C  */
		case   LBWop_ADD_ADDR_IMM8_v:/*Us=Un+C  */
		case   LBWop_ADD_ADDR_IMM8_w:/*Us=Un+C  */
			xx.registe(FT_ALU_agu, 0,n);
			xx.registe(FT_IMM, 0,n);
			return xx;


		/*only one bus resource for each cluster ,
		 * for the bus resource, Do not distinguish the out_bus and in_bus, please think deeply!!!,
		 * the distinguish  is not necessary !!!
		 */

		case   LBWop_TRANS_GR:
		case   LBWop_TRANS_GR_x_y:
		case   LBWop_TRANS_GR_x_z:
		case   LBWop_TRANS_GR_x_t:
			xx.push_usage(FT_BUS_X, NO_CORE,0);
				return xx;

		case   LBWop_TRANS_GR_y_x:
		case   LBWop_TRANS_GR_y_z:
		case   LBWop_TRANS_GR_y_t:
			xx.push_usage(FT_BUS_Y,NO_CORE, 0);
				return xx;

		case   LBWop_TRANS_GR_z_x:
		case   LBWop_TRANS_GR_z_y:
		case   LBWop_TRANS_GR_z_t:
			xx.push_usage(FT_BUS_Z,NO_CORE, 0);
			return xx;
		case   LBWop_TRANS_GR_t_x:
		case   LBWop_TRANS_GR_t_y:
		case   LBWop_TRANS_GR_t_z:
			xx.push_usage(FT_BUS_T,NO_CORE, 0);
				return xx;

		case   LBWop_TRANS_GR_DW:
		case   LBWop_TRANS_GR_DW_x_y:
		case   LBWop_TRANS_GR_DW_x_z:
		case   LBWop_TRANS_GR_DW_x_t:
			xx.push_usage(FT_BUS_X, NO_CORE, 0);
			xx.push_usage(FT_BUS_X, NO_CORE, 0);
				return xx;

		case   LBWop_TRANS_GR_DW_y_x:
		case   LBWop_TRANS_GR_DW_y_z:
		case   LBWop_TRANS_GR_DW_y_t:
			xx.push_usage(FT_BUS_Y, NO_CORE, 0);
			xx.push_usage(FT_BUS_Y, NO_CORE, 0);
				return xx;

		case   LBWop_TRANS_GR_DW_z_x:
		case   LBWop_TRANS_GR_DW_z_y:
		case   LBWop_TRANS_GR_DW_z_t:
			xx.push_usage(FT_BUS_Z, NO_CORE, 0);
			xx.push_usage(FT_BUS_Z, NO_CORE, 0);
				return xx;

		case   LBWop_TRANS_GR_DW_t_x:
		case   LBWop_TRANS_GR_DW_t_y:
		case   LBWop_TRANS_GR_DW_t_z:
			xx.registe(FT_BUS_T,NO_CORE, 0);
			xx.registe(FT_BUS_T,NO_CORE, 0);
				return xx;


		case   LBWop_MOV_IMM32_ADDR:/* Un(g)=C*/
		case   LBWop_MOV_IMM32_ADDR_u:
		case   LBWop_MOV_IMM32_ADDR_v:
		case   LBWop_MOV_IMM32_ADDR_w:

		case   LBWop_MOV_GR_ADDR:/* Um=Rs*/
		case   LBWop_MOV_GR_ADDR_x_u:
		case   LBWop_MOV_GR_ADDR_x_v:
		case   LBWop_MOV_GR_ADDR_x_w:

		case   LBWop_MOV_GR_ADDR_y_u:
		case   LBWop_MOV_GR_ADDR_y_v:
		case   LBWop_MOV_GR_ADDR_y_w:
		case   LBWop_MOV_GR_ADDR_z_u:
		case   LBWop_MOV_GR_ADDR_z_v:
		case   LBWop_MOV_GR_ADDR_z_w:
		case   LBWop_MOV_GR_ADDR_t_u:
		case   LBWop_MOV_GR_ADDR_t_v:
		case   LBWop_MOV_GR_ADDR_t_w:

		case   LBWop_MOV_ADDR_GR:
		case   LBWop_MOV_ADDR_GR_u_x:
		case   LBWop_MOV_ADDR_GR_u_y:
		case   LBWop_MOV_ADDR_GR_u_z:
		case   LBWop_MOV_ADDR_GR_u_t:
		case   LBWop_MOV_ADDR_GR_v_x:
		case   LBWop_MOV_ADDR_GR_v_y:
		case   LBWop_MOV_ADDR_GR_v_z:
		case   LBWop_MOV_ADDR_GR_v_t:
		case   LBWop_MOV_ADDR_GR_w_x:
		case   LBWop_MOV_ADDR_GR_w_y:
		case   LBWop_MOV_ADDR_GR_w_z:
		case   LBWop_MOV_ADDR_GR_w_t:
			return xx;
		default :
			L_punt("Get_Resource_Used: unexpected proc_opc %d ", proc_opc);
	}
}

